package com.liuyi.netty.im.lychat.modular.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapBuilder;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liuyi.netty.im.commons.codes.CodeConst;
import com.liuyi.netty.im.lychat.LychatConst;
import com.liuyi.netty.im.lychat.modular.caches.GroupMemberCache;
import com.liuyi.netty.im.lychat.modular.entity.Group;
import com.liuyi.netty.im.lychat.modular.entity.GroupMember;
import com.liuyi.netty.im.lychat.modular.entity.User;
import com.liuyi.netty.im.lychat.modular.enums.GroupRole;
import com.liuyi.netty.im.lychat.modular.enums.MessageReminding;
import com.liuyi.netty.im.lychat.modular.mapper.GroupMemberMapper;
import com.liuyi.netty.im.lychat.modular.service.IChatSessionService;
import com.liuyi.netty.im.lychat.modular.service.IGroupMemberService;
import com.liuyi.netty.im.lychat.modular.service.IGroupService;
import com.liuyi.netty.im.lychat.modular.service.IUserService;
import com.liuyi.netty.im.lychat.utils.JedisPoolUtil;
import com.liuyi.netty.im.server.util.ImHelp;
import com.liuyi.netty.im.server.util.ImUtil;
import com.liuyi.rapid.develop.tool.unusual.BizException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 * 群组成员表 服务实现类
 * </p>
 *
 * @author mybatis-plus
 * @since 2021-12-29
 */
@Service
public class GroupMemberServiceImpl extends ServiceImpl<GroupMemberMapper, GroupMember> implements IGroupMemberService {

    @Resource
    private GroupMemberCache cache;
    @Resource
    private IUserService userService;
    @Resource
    private IGroupService groupService;
    @Resource
    private IChatSessionService chatSessionService;

    @Override
    public GroupMemberCache cache() {
        return cache;
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void dissolveGroup(String groupId) {
        List<String> userIds = this.listObjs(q().eq(GroupMember.GROUP_NO, groupId).select(GroupMember.USER_ID), Convert::toStr);
        //删除关系
        this.remove(q().eq(GroupMember.GROUP_NO, groupId));
        String sessionId = ImHelp.sessionId(CodeConst.SessionType.GROUP, groupId);
        ImUtil.dissolveGroupMessage(groupId, "该群聊已被群主解散");
        //删除会话，以及相关缓存
        userIds.forEach(userId -> {
            chatSessionService.removeSession(userId, sessionId);
            cache.removeGetByUserIdAndGroupId(userId, groupId);
            cache.removeCountByUserIdAndGroupId(userId, groupId);
        });

        cache.removeListManageByGroupId(groupId);
        cache.removeListByGroupId(groupId);
    }

    @Override
    public GroupMember createGroup(String groupId, String userId) {
        GroupMember member = addMember(groupId, userId, GroupRole.MANAGE);
        ImUtil.addGroupMessage(groupId, member.getGroupNick().concat("创建了群聊"));
        return member;
    }

    @Override
    public GroupMember createGroup(String groupId, String userId, List<String> memberIds) {
        GroupMember member = addMember(groupId, userId, GroupRole.MANAGE);
        memberIds.forEach(item -> addMember(groupId, item, GroupRole.MEMBER));
        ImUtil.addGroupMessage(groupId, member.getGroupNick().concat("创建了群聊"));
        return member;
    }

    @Override
    public void addMember(String groupId, List<String> userIds) {
        if (userIds.size() > 10) {
            throw new BizException("抱歉，一次最多邀请10位群成员");
        }
        Group group = groupService.getById(groupId);
        if (group == null) {
            throw new BizException("群组不存在");
        }
        JedisPoolUtil.lock("GROUP_MEMBER_ADD:" + groupId, 3000, () -> {
            int merberCount = count(q().eq(GroupMember.GROUP_NO, groupId));
            if (merberCount >= LychatConst.GROUP_MAX_NUMBER) {
                throw new BizException("抱歉，当前群最大人数：" + LychatConst.GROUP_MAX_NUMBER + "人，不可邀请");
            }
            List<GroupMember> groupMembers = new ArrayList<>();
            List<String> userNicks = new ArrayList<>();
            userIds.forEach(userId -> {
                User user = userService.cache().getById(userId);
                if (user == null) {
                    throw new BizException("用户不存在");
                }
                if (count(q().eq(GroupMember.USER_ID, userId).eq(GroupMember.GROUP_NO, groupId)) == 0) {
                    //如果该用户不在该群组的话，就加入
                    GroupMember member = new GroupMember();
                    member.setGroupNo(groupId).setUserId(userId).setGroupRole(GroupRole.MEMBER)
                            .setMessageReminding(MessageReminding.RECEIVE_AND_REMIND)
                            .setGroupNick(user.getNick());
                    groupMembers.add(member);
                    userNicks.add(user.getNick());
                }
                cache.removeCountByUserIdAndGroupId(userId, groupId);
            });
            if (!groupMembers.isEmpty()) {
                if (merberCount + groupMembers.size() > LychatConst.GROUP_MAX_NUMBER) {
                    throw new BizException("抱歉，当前群人数：" + merberCount + "，当前群不可超过" + LychatConst.GROUP_MAX_NUMBER + "人，请重新选定人员邀请。");
                }
                this.saveBatch(groupMembers);
                cache().removeListByGroupId(groupId);
                ImUtil.addGroupMessage(groupId, "欢迎：".concat(CollUtil.join(userNicks, "，")).concat("加入群聊"));
            }
        });
    }

    @Override
    public void wrapper(GroupMember member) {
        if (member == null) {
            return;
        }
        Group group = groupService.cache().getById(member.getGroupNo());
        if (group != null) {
            member.setGroupName(group.getGroupName());
            member.setGroupHead(group.getGroupHead());
        }

        User user = userService.cache().getById(member.getUserId());
        if (user != null) {
            member.setUserHead(user.getHead());
        }

        member.setSessionId(ImHelp.sessionId(CodeConst.SessionType.GROUP, member.getGroupNo()));
    }

    @Override
    public Object groupProfile(String userId, String groupId) {
        if (StrUtil.isEmpty(userId) || StrUtil.isEmpty(groupId)) {
            return null;
        }
        GroupMember member = cache().getByUserIdAndGroupId(userId, groupId);
        if (member == null) {
            User user = userService.cache().getById(userId);
            if (user == null) {
                return MapBuilder.create(new HashMap<String, Object>())
                        .put("fromNick", "未知")
                        .put("fromHead", LychatConst.DEFAULT_USER_HEAD).build();

            }
            return MapBuilder.create(new HashMap<String, Object>())
                    .put("fromNick", user.getNick())
                    .put("fromHead", user.getHead()).build();
        }
        return MapBuilder.create(new HashMap<String, Object>())
                .put("fromNick", member.getGroupNick())
                .put("fromHead", member.getUserHead()).build();
    }

    private GroupMember addMember(String groupId, String userId, GroupRole groupRole) {
        User user = userService.cache().getById(userId);
        if (user == null) {
            throw new BizException("用户不存在");
        }
        Group group = groupService.cache().getById(groupId);
        if (group == null) {
            throw new BizException("群组不存在");
        }
        GroupMember member = new GroupMember();
        member.setGroupNo(groupId).setUserId(userId).setGroupRole(groupRole)
                .setMessageReminding(MessageReminding.RECEIVE_AND_REMIND)
                .setGroupNick(user.getNick());
        this.save(member);
        return member;
    }
}
